home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DNet / DGoAskDoc.cpp < prev    next >
Text File  |  1996-07-05  |  28KB  |  1,100 lines

  1. // DGopherAskDoc.cp
  2. // d.g.gilbert
  3.  
  4.  
  5.  
  6.  
  7. #include "DGoAskDoc.h"
  8. #include "DGoDoc.h"
  9. #include "DGoPrefs.h"
  10.  
  11. #include <ncbi.h>
  12. #include <dgg.h>
  13. #include <Dvibrant.h>
  14. #include <DApplication.h>
  15. #include <DGopher.h>
  16. #include <DGoList.h>
  17. #include <DGoInit.h>
  18. #include <DGoPlus.h>
  19. #include <DGoClasses.h>
  20. #include <DPanel.h>
  21. #include <DControl.h>
  22. #include <DDialogText.h>
  23. #include <DWindow.h>
  24. #include <DMenu.h>
  25. #include <DFile.h>
  26. #include <DUtil.h>
  27. #include <DIconLib.h> //??
  28. #include <DTaskCentral.h>
  29. #include <DURL.h>
  30.  
  31.  
  32.  
  33.  
  34. //class    DGopherAskDoc : public DWindow
  35.  
  36.  
  37.  
  38. enum AskConst {
  39.     kAskRowHeight = 25, 
  40.     kAskViewHeight = kAskRowHeight * 6,
  41.     kAskCol0Width = 50,
  42.     kAskColWidth = 250,
  43.     kAskViewWidth = kAskCol0Width + kAskColWidth,
  44.     kAskScrollTextHeight = 80,
  45.     cNextWind = 22456, cPrevWind, 
  46.     cOkayBut, cCancelBut
  47. };
  48.  
  49.  
  50.  
  51. DGopherAskDoc::DGopherAskDoc(long id, DGopher* itsGopher, 
  52.                 DGopherListDoc* itsMainDoc, short itsViewChoice):
  53.         DWindow( id, gApplication, document, -1, -1, -5, -5, NULL, kFreeOnClose),
  54.         fGopher(itsGopher), fMainDoc(itsMainDoc), fViewchoice(itsViewChoice),
  55.         fAskShort(NULL), fAskers(NULL), fControls(NULL),
  56.         fSendBut(NULL), fNextBut(NULL), fPrevBut(NULL),
  57.         fNumWindows(1), fAskFile(NULL), fChosenFile(NULL),
  58.         fPrevW(NULL), fNextW(NULL), fListStart(0), fListEnd(0)
  59. {
  60.     fGopher->newOwner();
  61.     if (!fGopher->fAskers) DGopherListDoc::ReadItemInfo(fGopher); // fetch from host now !?
  62.     if (!fGopher->fAskers) { delete this; return; }
  63.     fAskers= fGopher->fAskers;
  64.     fControls= new DList(); //(NULL, DList::kDeleteObjects); //!? no delete -- ~DView deleting subviews !
  65.     fNumWindows= this->NumOfWindows();
  66.     fIwindow= 1;
  67.     this->BuildWindows();
  68. }
  69.  
  70. DGopherAskDoc::DGopherAskDoc(long id, DGopherAskDoc* prevWindow, short listStart):
  71.         DWindow( id, gApplication, document, -1, -1, -5, -5, NULL, kFreeOnClose),
  72.         fAskShort(NULL), fAskers(NULL), fControls(NULL),
  73.         fSendBut(NULL), fNextBut(NULL), fPrevBut(NULL),
  74.         fNumWindows(1), fAskFile(NULL), fChosenFile(NULL),
  75.         fPrevW(prevWindow), fNextW(NULL), fListStart(listStart), fListEnd(0)
  76. {
  77.     fGopher=        prevWindow->fGopher;
  78.     fMainDoc=        prevWindow->fMainDoc;
  79.     fViewchoice=prevWindow->fViewchoice;
  80.     fNumWindows=prevWindow->fNumWindows;
  81.     fIwindow=        prevWindow->fIwindow+1;
  82.     fControls=     prevWindow->fControls;
  83.     fAskers=        prevWindow->fAskers;
  84.     this->BuildWindows();
  85. }
  86.  
  87.  
  88. DGopherAskDoc::~DGopherAskDoc()
  89. {
  90.     if (fNextW) {
  91.         delete fNextW; // delete chain of windows 
  92.         fNextW= NULL;
  93.         }
  94.     if (fPrevW) { 
  95.         fGopher= NULL;
  96.         fControls= NULL;
  97.         }
  98.     else { // first window
  99.         if (fGopher) fGopher->suicide();  fGopher= NULL;
  100.         if (fControls) delete fControls;  fControls= NULL;
  101.         }
  102.     if (fAskFile) MemFree(fAskFile);  fAskFile= NULL;
  103.     if (fChosenFile) fChosenFile->suicide(); // case we need suicide() -- fGopher MAY also be owner
  104. }
  105.  
  106. void DGopherAskDoc::BuildWindows()
  107. {    
  108.     char name[256];
  109.     if (fNumWindows>1) {
  110.         sprintf(name, "Ask (%d/%d) for %s", fIwindow, fNumWindows, fGopher->ShortName());
  111.         }
  112.     else {
  113.         StrCpy( name, "Ask for "); StrNCat( name, fGopher->ShortName(), 255);
  114.         }
  115.     this->SetTitle( name);
  116.         // put these buttons at top of window 
  117.     this->AddOkayCancelButtons(); 
  118.         
  119.     fAskShort= new DGopherAskShort( 0, this, fAskers, fControls);
  120.     fAskShort->InstallControls( fListStart, fListEnd);
  121.     if (fListEnd < fAskers->GetSize()) {
  122.         fNextW= new DGopherAskDoc(0,this,fListEnd);
  123.         }
  124. }
  125.  
  126. void DGopherAskDoc::Open()
  127. {
  128.     if (!fNextW) {  
  129.         if (fNextBut) fNextBut->Disable();
  130.             // user has seen all windows, let her send it
  131.         DGopherAskDoc* lastw= this;
  132.         while (lastw) {
  133.             if (lastw->fSendBut) lastw->fSendBut->Enable();
  134.             lastw= lastw->fPrevW;
  135.             }
  136.         }
  137.     if (!fPrevW && fPrevBut) fPrevBut->Disable();
  138.  
  139.     DWindow::Open();
  140. }
  141.  
  142. void DGopherAskDoc::OkayAction() 
  143. {
  144.     gCursor->watch();
  145.     this->DoReply();
  146.     gCursor->arrow();
  147. }
  148.  
  149.  
  150. void DGopherAskDoc::AddOkayCancelButtons()
  151. {
  152.         // we can't have a DDefaultButton here, it eats all Return keys !
  153.     DButton* bb= new DButton( cCancelBut, this, "Cancel");
  154.     //bb->SetResize( DView::fixed, DView::moveinsuper);  
  155.     this->NextSubviewToRight();
  156.     fSendBut= new DButton( cOkayBut, this, "Send");  
  157.     if (fNumWindows > 1) {
  158.         fSendBut->Disable(); // keep disabled until all windows visited !?
  159.         this->NextSubviewToRight();
  160.         fPrevBut= new DButton( cPrevWind, this, "Previous");
  161.         this->NextSubviewToRight();
  162.         fNextBut= new DButton( cNextWind, this, "Next");  
  163.         } 
  164.     this->NextSubviewBelowLeft();
  165. }
  166.  
  167. void DGopherAskDoc::Close() 
  168. {
  169.     // using fFreeOnClose so this deletes each win
  170. #if 1
  171.         // close only 1st window, its destructor closes&frees all others
  172.     DGopherAskDoc * lastw;
  173.     lastw= this->fPrevW;
  174.     if (lastw) {
  175.       while (lastw->fPrevW) lastw= lastw->fPrevW;
  176.         lastw->Close();
  177.         }
  178.     else
  179.         DWindow::Close();
  180. #else
  181.     DGopherAskDoc * otherw, * next;
  182.     next= this->fPrevW;
  183.     while (next) {
  184.         otherw= next;
  185.         next= next->fPrevW;
  186.         //otherw->Close();
  187.         }
  188.     next= this->fNextW;
  189.     while (next) {
  190.         otherw= next;
  191.         next= next->fNextW;
  192.         otherw->Close();
  193.         }
  194.     DWindow::Close();
  195. #endif
  196. }
  197.  
  198. Boolean DGopherAskDoc::IsMyAction(DTaskMaster* action) 
  199. {    
  200.     char  buf[512];
  201.  
  202.     switch(action->Id()) {
  203.  
  204.         case kGopherAskAskF : {
  205.             char* filename= (char*)gFileManager->GetOutputFileName(this->fAskFile);
  206.             if (filename) {
  207.                 this->fAskFile= StrDup(filename);  
  208.                 char* shortName= (char*)gFileManager->FilenameFromPath(this->fAskFile);
  209.                 sprintf(buf, "Get: %s", shortName);
  210.                 ((DView*) action)->SetTitle(buf);  
  211.                 // !? need also to resize the button to show all of name !?
  212.                 }
  213.             }
  214.             return true;
  215.             
  216.         case kGopherAskChooseF :  {
  217.             //char* filename= (char*)gFileManager->GetInputFileName(".txt","TEXT");
  218.             char* filename= (char*)gFileManager->GetInputFileName(NULL,NULL);
  219.             if (filename) {
  220.                 if (this->fChosenFile) delete this->fChosenFile;
  221.                 this->fChosenFile= new DFile(filename,"r");
  222.                 char* shortName= (char*)gFileManager->FilenameFromPath(filename);
  223.                 sprintf(buf, "Send: %s", shortName);
  224.                 ((DView*) action)->SetTitle(buf); 
  225.                 // !? need also to resize the button to show all of name !?
  226.                 }
  227.             }
  228.             return true;
  229.  
  230.         case cNextWind:
  231.             if (fNextW) {
  232.                 fNextW->Open();
  233.                 this->Hide();
  234.                 }
  235.             return true;
  236.             
  237.         case cPrevWind:
  238.             if (fPrevW) {
  239.                 fPrevW->Open();
  240.                 this->Hide();
  241.                 }
  242.             return true;
  243.             
  244.         case cOkayBut:
  245.             this->OkayAction();
  246.             fOkay= true;
  247.             // fall thru to next case
  248.         case cCancelBut: 
  249.             fModal= false;
  250.             this->CloseAndFree();  
  251.             return true;
  252.             
  253.         default:
  254.             return DWindow::IsMyAction(action);    
  255.         }
  256. }
  257.  
  258.  
  259. short    DGopherAskDoc::NumOfWindows()
  260. {
  261.     long     irow, nask, len;    
  262.     short    height= 0;
  263.     short lineheight, buttonheight;
  264.     short screenwidth, screenheight;
  265.     gUtil->screensize( screenwidth, screenheight);
  266.     screenheight -= 40; // don't fill entire screen;
  267.  
  268.         // some items use gGoviewFont, some Nlm_systemFont
  269.     Nlm_SelectFont(gGoviewFont);
  270.     lineheight= Nlm_LineHeight();  
  271.     //lineheight= 2 + Max(Max(Nlm_stdLineHeight, Nlm_LineHeight()), kAskRowHeight);  
  272.     buttonheight= Nlm_stdLineHeight + 10; // this +10 fiddle varies w/ window_os, but 10 is max
  273.     
  274.     // remove fudge for OKAY/CANCEL and window space
  275.     screenheight -= buttonheight * 2;
  276.  
  277.     nask= fAskers->GetSize();
  278.     for (irow = 0; irow<nask; irow++) {
  279.         DGopherItemAsk* anAsker= (DGopherItemAsk*) fAskers->At(irow);
  280.         switch (anAsker->fKind) {
  281.             case kGopherAskAsk:        //edittext
  282.             case kGopherAskNote:     //prompt
  283.                 height += lineheight;
  284.                 break;
  285.             case kGopherAskChoose:     // popup    
  286.             case kGopherAskSelect:     // checkbox
  287.             case kGopherAskChooseF: // button
  288.             case kGopherAskAskF:        // button
  289.                 height += buttonheight;
  290.                 break;
  291.             case kGopherAskAskP:        // passwordtext
  292.             default : 
  293.                 height += Nlm_stdLineHeight;
  294.                 break;
  295.             case kGopherAskAskL:        // dialog text
  296.                 height += kAskScrollTextHeight + Nlm_hScrollBarHeight + 6;
  297.                 break;
  298.             }
  299.         }
  300.     return ((height + screenheight-1) / screenheight);
  301. }
  302.  
  303.  
  304.  
  305.  
  306. void DGopherAskDoc::DoReply()
  307. {
  308.     enum { cProcessGopher = 30346 };
  309.     DFile* replyFile= NULL;
  310.     char* replies= this->Answers(replyFile);
  311.  
  312.     DGopher* aGopher = (DGopher*) fGopher->Clone();  
  313.     aGopher->SetAskReply( replies, replyFile);
  314.     aGopher->fViewchoice= fViewchoice;
  315.     aGopher->fStatusLine= NULL; //??
  316.     
  317.     //DTask* aTask= fMainDoc->newTask(cProcessGopher, DGopherListDoc::kGoListdoc, (long) aGopher); 
  318.     //fMainDoc->PostTask( aTask); 
  319.     DTask* aTask= new DTask( cProcessGopher, DGopherListDoc::kGoListdoc,
  320.                                      gGopherDoc, (long) aGopher);
  321.     gTaskCentral->AddTask(aTask);
  322. }
  323.  
  324.  
  325.  
  326. char* DGopherAskDoc::Answers(DFile*& replyFile)
  327. {
  328.     // ASK data return is 
  329.     // path<tab>+<tab>1<crlf> 
  330.     // +-1<crlf>
  331.     // data...<crlf>
  332.     // data...<crlf>
  333.     // .<crlf>
  334.  
  335.     char *ans;
  336.     long    iask, nask;
  337.     char  aline[256], *bline;
  338.     DCluster* clus;
  339.     DView* aControl;
  340.     
  341.     replyFile= NULL;
  342.     ans    = (char*)MemNew(1);
  343.     *ans= 0;
  344.     nask= fAskers->GetSize();
  345.     
  346.     Boolean isHTMLForm= (fGopher->fHasAsk == 3 || fGopher->fHasAsk == 5);
  347.     Boolean isHTMLPostForm= (fGopher->fHasAsk == 5);
  348.         
  349.     for (iask = 0; iask<nask; iask++) {
  350.         DGopherItemAsk* anAsker= (DGopherItemAsk*) fAskers->At(iask);
  351.         DGopherItemAsk* origAsker= NULL;
  352.         origAsker= anAsker;   //??
  353.  
  354.         aControl= (DView*) fControls->At(iask);
  355.         
  356.         if (anAsker!=NULL && aControl!=NULL) {
  357.             if (isHTMLForm) {
  358.                 StrExtendCat( &ans, anAsker->fNametag);
  359.                 StrExtendCat( &ans, "=");
  360.                 }
  361.                 
  362.          switch (anAsker->fKind) {
  363.  
  364.             case kGopherAskAsk:    
  365.             case kGopherAskAskP:    
  366.                     aControl->GetTitle(aline, 250);
  367.                     if (origAsker) origAsker->SetAnswer( aline); // preserve answer for next use
  368.                     if (isHTMLForm) {
  369.                         bline= DURL::EncodeChars( aline);
  370.                         if (isHTMLPostForm) StrCat(bline, CRLF);
  371.                         StrExtendCat( &ans, bline);
  372.                         MemFree( bline);
  373.                         }
  374.                     else {
  375.                         StrCat(aline, CRLF);
  376.                         StrExtendCat( &ans, aline);
  377.                         }
  378.                     break;
  379.                 
  380.             case kGopherAskAskF:    
  381.                     // send server file *name* chosen by user for local file
  382.                     if (fAskFile) {
  383.                         StrNCpy(aline, fAskFile, 250);
  384.                         if (origAsker) origAsker->SetAnswer( aline); // preserve answer for next use
  385.                         }
  386.                     else *aline= 0;
  387.                     if (isHTMLForm) {
  388.                         // no html equivalent...
  389.                         }
  390.                     else {
  391.                         StrCat(aline, CRLF);
  392.                         StrExtendCat( &ans, aline);
  393.                         }
  394.                     break;
  395.                     
  396.             case kGopherAskChoose:    
  397.                     {
  398.                     short choice;
  399.                     //choice=  aControl->GetValue();
  400.                     //aControl->GetItemTitle( choice, aline, 250);
  401.                     DPopupList* pop= (DPopupList*) aControl;
  402.                     pop->GetSelectedItem( choice, aline, 250);
  403.                     if (origAsker) origAsker->ItemChoice( choice); // preserve item for next use
  404.                     if (isHTMLForm) {
  405.                     
  406.                         // ! HTML uses valuetags for each radio item
  407.                         StrCpy(aline, anAsker->fValuetag);
  408.                         
  409.                         bline= DURL::EncodeChars( aline);
  410.                         if (isHTMLPostForm) StrCat(bline, CRLF);
  411.                         StrExtendCat( &ans, bline);
  412.                         MemFree( bline);
  413.                         }
  414.                     else {
  415.                         StrCat(aline, CRLF);
  416.                         StrExtendCat( &ans, aline);
  417.                         }
  418.                     }
  419.                     break;
  420.  
  421.             case kGopherAskSelect: 
  422.                     if ( aControl->GetStatus() )  
  423.                         StrCpy(aline,"1");
  424.                     else 
  425.                         StrCpy(aline,"0");
  426.                     if (origAsker) origAsker->SetAnswer( aline); // preserve answer for next use
  427.  
  428.                     if (isHTMLForm ) {
  429.                         if ( aControl->GetStatus() ) {
  430.                             // html uses value string for each select/checkbox item
  431.                             StrCpy(aline, anAsker->fValuetag);
  432.                             bline= DURL::EncodeChars( aline);
  433.                             if (isHTMLPostForm) StrCat(bline, CRLF);
  434.                             StrExtendCat( &ans, bline);
  435.                             MemFree( bline);
  436.                             }
  437.                         }
  438.                         
  439.                     else {
  440.                         StrCat(aline, CRLF);
  441.                         StrExtendCat( &ans, aline);
  442.                         }
  443.                     break;
  444.                     
  445.             case kGopherAskChooseF:
  446.                     // this goes to replyFile... ??
  447.                     replyFile= fChosenFile; // maybe NULL
  448.                     if (replyFile) replyFile->newOwner();
  449.                     // does protocol require an empty writeline here for server ???
  450.                     break;
  451.                     
  452.             case kGopherAskAskL:
  453.                     {
  454.                     char *txt, *cp, *ep;
  455.                     long len, nlines= 0;
  456.                     txt= aControl->GetText();
  457.                     
  458.                     if (isHTMLForm) {
  459.                         bline= DURL::EncodeChars( txt);
  460.                         if (isHTMLPostForm) StrCat(bline, CRLF);
  461.                         StrExtendCat( &ans, bline);
  462.                         MemFree( bline);
  463.                         }
  464.                     else {
  465.  
  466.                     // ! first need to count & write # of lines in txt...                
  467.                      for (short first= 1; first<=2; first++) {
  468.                         for (cp= txt; cp && *cp; ) {
  469.                             for (ep=cp; *ep != 0 && *ep != kCR && *ep != kLF; ep++) ;
  470.                             len= ep - cp;
  471.                             if (ep && len>0) {
  472.                                 if (first==1) nlines++;
  473.                                 else {
  474.                                     if (len > 250) len= 250;
  475.                                     StrNCpy( aline, cp, len);
  476.                                     aline[len]= 0;
  477.                                     StrCat( aline, CRLF);
  478.                                     StrExtendCat( &ans, aline);
  479.                                     }
  480.                                 }
  481.                             cp= ep;
  482.                             if (cp && *cp) {
  483.                                 if (*cp == kCR && *(cp+1) == kLF) cp += 2;
  484.                                 else cp++;
  485.                                 }
  486.                             }
  487.                         if (first==1) { 
  488.                             sprintf(aline, "%d"CRLF, nlines);
  489.                             StrExtendCat( &ans, aline);
  490.                             }
  491.                         }
  492.                     }
  493.                     MemFree(txt);
  494.                     }
  495.                     break;
  496.                     
  497.             case kGopherAskNote: 
  498.             default : 
  499.                     break;
  500.             }
  501.          }
  502.         }
  503.     
  504.     return ans;
  505. }
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513. // class DGopherAskShort
  514.  
  515. DGopherAskShort::DGopherAskShort(long id, DGopherAskDoc* itsSuperior, 
  516.     DList* itsAskers, DList* itsControls) :
  517.     DCluster( id, itsSuperior, -1, -1, true, NULL),
  518.     fAskers(itsAskers),
  519.     fDoc(itsSuperior),
  520.     fControls(itsControls)
  521. {
  522.     this->SetResize( DView::matchsuper, DView::relsuper); //??
  523. }
  524.  
  525.  
  526. DGopherAskShort::~DGopherAskShort()
  527. {
  528. }
  529.  
  530.  
  531. Boolean DGopherAskShort::IsMyAction(DTaskMaster* action) 
  532. {
  533.     switch(action->Id()) {
  534.  
  535.         default:
  536.             return DCluster::IsMyAction(action);
  537.  
  538.         }
  539. }
  540.  
  541.  
  542.  
  543. void    DGopherAskShort::InstallControls(short startControl, short& endControl)
  544. {
  545.     short             irow, nask;
  546.     short             lineheight, maxlineheight, dialogheight, screenwidth, screenheight;
  547.     DView            * super, *aview;
  548.     DCluster    * cluster1;
  549.     DPrompt        * pr;
  550.     DGopherItemAsk * anAsker;
  551.     Nlm_PoinT        nextpos;
  552.     Nlm_RecT         aloc;
  553.     
  554.     gUtil->screensize( screenwidth, screenheight);
  555.     screenheight -= 40; // don't fill entire screen;
  556.  
  557.     Nlm_SelectFont(gGoviewFont);
  558.     lineheight= Nlm_LineHeight();  
  559.     maxlineheight= 10 + Max(Nlm_stdLineHeight, lineheight); //??
  560.     this->GetNextPosition(&nextpos);
  561.     dialogheight= nextpos.y + maxlineheight;
  562.      
  563.     nask= fAskers->GetSize();
  564.     super= this;
  565.     
  566.     for (irow = startControl; irow<nask && dialogheight<screenheight; irow++) {
  567.         endControl= irow+1;
  568.         
  569.             // need this stupid extra for formatting ?
  570.         cluster1 = new DCluster( 0, super, 0,0, true);
  571.         cluster1->SetResize( DView::relsuper, DView::fixed); // not for all, only some !
  572.         super    = cluster1;
  573.  
  574.         anAsker= (DGopherItemAsk*) fAskers->At(irow);
  575.  
  576.         pr= new DPrompt( 0, super, anAsker->fQuestion, 0, 0, gGoviewFont);             
  577.         super->NextSubviewToRight();
  578.         aview= NULL;
  579.  
  580.         switch (anAsker->fKind) {
  581.         
  582.             case kGopherAskAskP:    
  583.                 aview = new DPasswordText(anAsker->fKind, super, NULL, 15);
  584.                 aview->SetTitle(anAsker->fAnswer);
  585.                 aview->SetResize( DView::relsuper, DView::fixed);
  586.                 break;
  587.     
  588.             case kGopherAskAsk:    
  589.                 aview = new DEditText(anAsker->fKind, super, NULL, 15, gGoviewFont);
  590.                 aview->SetTitle(anAsker->fAnswer);
  591.                 aview->SetResize( DView::relsuper, DView::fixed);
  592.                 break;
  593.                     
  594.             case kGopherAskAskL:
  595.                 {
  596.                 short width = 20;  
  597.                 short height= (kAskScrollTextHeight + lineheight-1) / lineheight; 
  598.                 aview = new DDialogScrollText(anAsker->fKind, super, width, height, gTextFont, false);
  599.                 aview->SetTitle( anAsker->fAnswer);
  600.                 aview->SetResize( DView::relsuper, DView::fixed);
  601.                 }
  602.                 break;
  603.  
  604.             case kGopherAskChooseF:
  605.             case kGopherAskAskF:    
  606.                 {
  607.                 char* name = anAsker->fAnswer;
  608.                 if (name == NULL || *name == 0) {
  609.                     if (anAsker->fKind == kGopherAskAskF) name= "New file from server";
  610.                     else name= "Choose file to send";
  611.                     }
  612.                 aview = new DButton( anAsker->fKind, super, name);
  613.                 }
  614.                 break;
  615.                                     
  616.  
  617.             case kGopherAskSelect:
  618.                 {
  619.                 Boolean ison= false;
  620.                 char* answer = anAsker->fAnswer;
  621.                 if (answer) {
  622.                     while (*answer && isspace(*answer)) answer++;
  623.                     ison= (*answer == '1' || *answer == 'T' || *answer == 't');
  624.                     }
  625.                 else {
  626.                     //  UMinn example select doesn't use TAB to separate quest & answer
  627.                     //  strings like other ASK items, uses ':' !!!
  628.                     answer= StrChr(anAsker->fQuestion,':');
  629.                     if (answer) {
  630.                         answer++;
  631.                         ison= (*answer != '0');
  632.                         }
  633.                     }
  634.                 aview = new DCheckBox( anAsker->fKind, super, NULL);
  635.                 aview->SetStatus( ison);
  636.                 }
  637.                 break;
  638.                             
  639.             
  640.             case kGopherAskChoose:    
  641.                 {
  642.                 char *cp, *ep;
  643.                 Boolean done;
  644.                 DPopupList* aPopup = new DPopupList(anAsker->fKind, super, true);
  645.                 
  646.                 char *words= StrDup( anAsker->fAnswer);
  647.                 for (cp= words, done=false; !done && *cp!=0; ) {
  648.                     ep= strchr( cp, '\t');
  649.                     if (!ep) {
  650.                         ep=strchr( cp, '\0');
  651.                         done= true;
  652.                         }
  653.                   if (ep) {
  654.                         *ep= 0;
  655.                         aPopup->AddItem( cp);
  656.                         if (!done) cp= ep+1;
  657.                         }
  658.                     else
  659.                         done= true;
  660.                     }
  661.                 MemFree( words);
  662.                 aPopup->SetValue(1);
  663.                 aview= aPopup;
  664.                 }
  665.                 break;
  666.                 
  667.             case kGopherAskNote: 
  668.             default : 
  669.                 aview = new DPrompt( anAsker->fKind, super, anAsker->fAnswer, 0, 0, gGoviewFont);
  670.                 //aview->SetResize( DView::relsuper, DView::fixed);
  671.                 break;
  672.             }
  673.             
  674.         if (aview) fControls->InsertLast(aview);
  675.         super= this;
  676.         super->NextSubviewBelowLeft();
  677.         super->GetNextPosition(&nextpos);
  678.         dialogheight= nextpos.y + maxlineheight;
  679.         }
  680.         
  681. }
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691. #ifdef THIS_IS_OBSOLETE
  692.  
  693. ///////////////////////////////////////////////////////////////////////
  694. //
  695. //                 THIS DIALOG W/ SCROLLING CONTROLS ISN'T WORKING
  696. //        VIBRANT ISN'T UP TO MANAGING CONTROLS THAT ARE SCROLLED
  697. //        IN&OUT OF A VIEW.    Try multiple windows instead.
  698. //
  699. ///////////////////////////////////////////////////////////////////////
  700.  
  701.  
  702.  
  703. // class DGopherAskView
  704. class DGopherAskView : public DTableView, public DKeyCallback
  705. {
  706. public:
  707.     DList* fControls;
  708.     DList* fAskers;
  709.     DDialogText*    fEditText;
  710.     DGopherAskDoc*    fDoc;
  711.     
  712.     DGopherAskView(long id, DGopherAskDoc* itsSuperior, DList* itsAskers, short pixwidth, short pixheight);
  713.     virtual ~DGopherAskView();
  714.  
  715.     virtual Boolean IsMyAction(DTaskMaster* action);
  716.     virtual void  InstallControls(DList* theControls);
  717.     
  718.     virtual void Click(Nlm_PoinT mouse);    
  719.     virtual void CharHandler(char c);
  720.   virtual void ProcessKey(char c);
  721.     virtual void SetEditText(DDialogText* theText);
  722.     virtual void DrawRow(Nlm_RecT r, short row);
  723.     virtual void SetClusterPositions();
  724.     virtual void Scroll(Boolean vertical, DView* scrollee, short newval, short oldval);
  725.     
  726.     //virtual void Drag(Nlm_PoinT mouse);
  727.     //virtual void Hold(Nlm_PoinT mouse);
  728.     //virtual void Release(Nlm_PoinT mouse);
  729. };
  730.  
  731.  
  732.  
  733. class  DAskEditText : public DEditText
  734. {
  735. public:
  736.     DGopherAskView* fAskView;
  737.     DAskEditText( DGopherAskView* itsView, long id, DView* superior, char* name, short width) :
  738.         DEditText( id, superior, name, width),
  739.         fAskView(itsView) 
  740.         { }
  741.     virtual void selectAction() { fAskView->SetEditText(this); }
  742.     virtual void deselectAction() { fAskView->SetEditText(NULL); }
  743. };
  744.  
  745. class  DAskPasswordText : public DPasswordText
  746. {
  747. public:
  748.     DGopherAskView* fAskView;
  749.     DAskPasswordText( DGopherAskView* itsView, long id, DView* superior, char* name, short width) :
  750.         DPasswordText( id, superior, name, width),
  751.         fAskView(itsView) 
  752.         { }
  753.     virtual void selectAction() { fAskView->SetEditText(this); }
  754.     virtual void deselectAction() { fAskView->SetEditText(NULL); }
  755. };
  756.  
  757. class  DAskScrollText : public DDialogScrollText
  758. {
  759. public:
  760.     DGopherAskView* fAskView;
  761.     DAskScrollText( DGopherAskView* itsView, long id, DView* superior,
  762.             short width, short height, Nlm_FonT font, Boolean wrap) :
  763.         DDialogScrollText( id, superior, width, height, font, wrap),
  764.         fAskView(itsView) 
  765.         { }
  766.     virtual void selectAction() { fAskView->SetEditText(this); }
  767.     virtual void deselectAction() { fAskView->SetEditText(NULL); }
  768. };
  769.  
  770.  
  771.  
  772. DGopherAskView::DGopherAskView(long id, DGopherAskDoc* itsSuperior, DList* itsAskers,
  773.                 short pixwidth, short pixheight):
  774.         DTableView( id, itsSuperior, pixwidth, pixheight, 2/*nrows*/, 2/*cols*/, 
  775.                             kAskColWidth/*itemwidth*/, kAskRowHeight/*itemheight*/),
  776.         fControls(NULL),
  777.         fEditText(NULL),
  778.         fDoc(itsSuperior),
  779.         fAskers(itsAskers)
  780. {
  781.     // FailNIL(fAskers);
  782.     this->SetSlateBorder(false);
  783.     this->SetResize( DView::matchsuper, DView::relsuper);
  784. }
  785.  
  786. DGopherAskView::~DGopherAskView()
  787. {
  788.  
  789. }
  790.  
  791.  
  792.  
  793. void DGopherAskView::SetEditText(DDialogText* theText)
  794. {
  795.     if (!theText && fEditText) {
  796.         fEditText->SetSelection(0,0); // no other deselect method?
  797.         }
  798.     fEditText= theText; 
  799.     GetWindow()->SetEditText(fEditText); 
  800.     if (fEditText) {
  801.         fEditText->Enable(); // not needed?
  802.         fEditText->Select(); 
  803.         }
  804. }
  805.  
  806.  
  807. void DGopherAskView::CharHandler(char c) 
  808. {
  809.         // this is a vibrant SlatE callback -- not called
  810.     this->ProcessKey(c);
  811. }
  812.  
  813. void DGopherAskView::ProcessKey(char c) 
  814. {
  815.         // this works -- general key callback from vibrant,
  816.         // but the above vibrant SlatE callback doesn't get called
  817. #ifdef WIN_MAC    
  818.     if (fEditText) { 
  819.         Nlm_GraphiC  g = (Nlm_GraphiC)fEditText->GetNlmObject();
  820.         Nlm_GphPrcsPtr classPtr= Nlm_GetClassPtr( g);
  821.         if (classPtr) {
  822.             Nlm_BGphChr keyproc= classPtr->key;
  823.             if (keyproc && (*keyproc)(g, c)) ;
  824.             }
  825.         }
  826. #endif
  827. }
  828.  
  829. void DGopherAskView::Click(Nlm_PoinT mouse)
  830. {
  831.     short row, col;
  832.     PointToCell( mouse, row, col);
  833.     DView* ac= (DView*) fControls->At(row); 
  834.     if (!ac) return;
  835.     
  836.     DView* subview = NULL;
  837.     if ( (subview = ac->FindSubview(kGopherAskAsk )) != NULL
  838.       || (subview = ac->FindSubview(kGopherAskAskP)) != NULL
  839.       || (subview = ac->FindSubview(kGopherAskAskL)) != NULL )
  840.           {
  841.             fEditText= (DDialogText*) subview;
  842.             this->GetWindow()->SetEditText(fEditText); 
  843.             fEditText->Select(); 
  844.             this->SetKeyHandler(this);
  845.             }
  846.             
  847. #ifdef WIN_MAC
  848.     {
  849.     Nlm_GraphiC          g = (Nlm_GraphiC)ac->GetNlmObject();
  850.     Nlm_GphPrcsPtr     classPtr  = Nlm_GetClassPtr( g);
  851.     if (classPtr) {
  852.         Nlm_BGphPnt         groupclick= classPtr->click;
  853.         if (groupclick && (*groupclick)(g, mouse)) ;
  854.         }
  855.     }
  856. #endif
  857. }
  858.  
  859. void DGopherAskView::DrawRow(Nlm_RecT r, short row)
  860. {
  861.     Nlm_InsetRect(&r, 2, 2);
  862.   Nlm_SelectFont(gGoviewFont);
  863.     
  864.     // draw both text in col0 and control in col1 !!
  865.     DGopherItemAsk* anAsker= (DGopherItemAsk*) fAskers->At(row);
  866.     if (anAsker && anAsker->fQuestion) {
  867.         Nlm_DrawString( &r, anAsker->fQuestion, 'l', false);
  868.         r.left += 5 + Min(500, Max( kAskCol0Width, Nlm_StringWidth(anAsker->fQuestion)));
  869.         }
  870.         
  871.     DView* ac= (DView*) fControls->At(row); 
  872.     if (ac) {
  873. #if 0
  874.                 // having problems w/ control getting drawn as big as IT wants, not clipped to this view...
  875.                 // this ain't helping
  876.       Nlm_RecT clipr;
  877.         Nlm_SectRect( &r, &Nlm_updateRect, &clipr);
  878.         Nlm_ClipRect( &clipr);
  879. #endif
  880.         ac->SetPosition( r);
  881.         ac->Show();
  882.         }
  883. }
  884.  
  885. void DGopherAskView::SetClusterPositions()
  886. {
  887.     Nlm_RecT r;
  888. #if 1
  889.   Nlm_SelectFont(gGoviewFont);
  890. #endif
  891.     for (short arow= fTop; arow< fMaxRows; arow++ ) {
  892. #if 1
  893.         GetRowRect( arow, r);
  894.         DGopherItemAsk* anAsker= (DGopherItemAsk*) fAskers->At(arow);
  895.         if (anAsker && anAsker->fQuestion) {
  896.             r.left += 5 + Min(500, Max( kAskCol0Width, Nlm_StringWidth(anAsker->fQuestion)));
  897.             }
  898. #else
  899.         GetCellRect( arow, 1, r);
  900. #endif
  901.         if (Nlm_RectInRect( &r, &fRect)) {
  902.             DView* ac= (DView*) fControls->At(arow); 
  903.             if (ac) {
  904.                 Nlm_InsetRect( &r, 2, 2);
  905.                 ac->SetPosition( r);
  906.                 Nlm_ValidRect( &r); // ??
  907.                 }
  908.             }
  909.         }
  910. }
  911.  
  912. void DGopherAskView::Scroll(Boolean vertical, DView* scrollee, short newval, short oldval)
  913. {
  914.     DTableView::Scroll(vertical, scrollee, newval, oldval);
  915.     this->SetClusterPositions(); // !! need this if default scroll is used that scrolls bitmap!
  916. }
  917.  
  918.  
  919. Boolean DGopherAskView::IsMyAction(DTaskMaster* action) 
  920. {
  921.     char  buf[512];
  922.     
  923.     switch(action->Id()) {
  924.  
  925.         case kGopherAskAskF : {
  926.             char* filename= (char*)gFileManager->GetOutputFileName(fDoc->fAskFile);
  927.             if (filename) {
  928.                 fDoc->fAskFile= StrDup(filename);  
  929.                 char* shortName= (char*)gFileManager->FilenameFromPath(fDoc->fAskFile);
  930.                 sprintf(buf, "Get: %s", shortName);
  931.                 ((DView*) action)->SetTitle(buf);  
  932.                 // !! need also to resize the button to show all of name !
  933.                 }
  934.             }
  935.             return true;
  936.             
  937.         case kGopherAskChooseF :  {
  938.             char* filename= (char*)gFileManager->GetInputFileName(".txt","TEXT");
  939.             if (filename) {
  940.                 if (fDoc->fChosenFile) delete fDoc->fChosenFile;
  941.                 fDoc->fChosenFile= new DFile(filename,"r");
  942.                 char* shortName= (char*)gFileManager->FilenameFromPath(filename);
  943.                 sprintf(buf, "Send: %s", shortName);
  944.                 ((DView*) action)->SetTitle(buf); 
  945.                 // !! need also to resize the button to show all of name !
  946.                 }
  947.             }
  948.             return true;
  949.  
  950.         default:
  951.             return DTableView::IsMyAction(action);
  952.             break;
  953.         }
  954. }
  955.  
  956.  
  957.  
  958. void    DGopherAskView::InstallControls(DList* theControls)
  959. {
  960.     long                 irow, nask, len;
  961.     Nlm_RecT         aloc;
  962.     DCluster    * cluster = NULL;
  963.     DView                *super, *aview;
  964.     char                *defstring, *kPlaceholder = "             "; // 13 spaces
  965.     
  966.     fControls= theControls;
  967.     nask= fAskers->GetSize();
  968.     this->SetTableSize( nask, 2);
  969.  
  970.     aloc.bottom = 20;
  971.     for (irow = 0; irow<nask; irow++) {
  972.         aview= NULL;
  973.         DGopherItemAsk* anAsker= (DGopherItemAsk*) fAskers->At(irow);
  974.         this->GetCellRect( irow, 1, aloc); //?? how many cols ??
  975.  
  976.             // !! MUST HAVE DCluster() for popups to work !
  977.             // edittext still won't take keypresses...
  978.         cluster= new DCluster( 0, this, 100, 50, true, NULL);
  979.         cluster->SetResize( DView::relsuper, DView::fixed); // not for all, only some !
  980.         super= cluster;
  981.  
  982.         switch (anAsker->fKind) {
  983.         
  984.             case kGopherAskAskP:    
  985.                 aview = new DAskPasswordText( this, anAsker->fKind, super, kPlaceholder, 15);
  986.                 aview->SetTitle(anAsker->fAnswer);
  987.                 aview->SetResize( DView::relsuper, DView::fixed);
  988.                 break;
  989.     
  990.             case kGopherAskAsk:    
  991.                 aview = new DAskEditText( this, anAsker->fKind, super, kPlaceholder, 15);
  992.                 aview->SetResize( DView::relsuper, DView::fixed);
  993.                 aview->SetTitle(anAsker->fAnswer);
  994.                 break;
  995.                     
  996.             case kGopherAskAskL:
  997.                 {
  998.                 this->SetItemHeight( irow, 1, kAskScrollTextHeight + Nlm_hScrollBarHeight + 6);
  999.                 aloc.bottom = aloc.top + kAskScrollTextHeight;
  1000.                         // !! these sizes are in stdCharWidth chars !!! not pixels
  1001.                 aloc.right -=    Nlm_vScrollBarWidth;
  1002.                 short width = (aloc.right - aloc.left) / Nlm_stdCharWidth;  
  1003.                 short height= (aloc.bottom - aloc.top) / Nlm_stdLineHeight; 
  1004.                 aview = new DAskScrollText( this, anAsker->fKind, super, width, height, gTextFont, false);
  1005.                 aview->SetTitle( anAsker->fAnswer);
  1006.                 aview->SetResize( DView::relsuper, DView::fixed);
  1007.                 }
  1008.                 break;
  1009.  
  1010.             case kGopherAskChooseF:
  1011.             case kGopherAskAskF:    
  1012.                 {
  1013.                 char* name = anAsker->fAnswer;
  1014.                 if (name == NULL || *name == 0) {
  1015.                     if (anAsker->fKind == kGopherAskAskF) name= "New file from server";
  1016.                     else name= "Choose file to send";
  1017.                     }
  1018.                 aview = new DButton( anAsker->fKind, super, name);
  1019.                 }
  1020.                 break;
  1021.                                     
  1022.  
  1023.             case kGopherAskSelect:
  1024.                 {
  1025.                 Boolean ison= false;
  1026.                 char* answer = anAsker->fAnswer;
  1027.                 if (answer) {
  1028.                     while (*answer && isspace(*answer)) answer++;
  1029.                     ison= (*answer == '1' || *answer == 'T' || *answer == 't');
  1030.                     }
  1031.                 else {
  1032.                     //  UMinn example select doesn't use TAB to separate quest & answer
  1033.                     //  strings like other ASK items, uses ':' !!!
  1034.                     answer= StrChr(anAsker->fQuestion,':');
  1035.                     if (answer) {
  1036.                         answer++;
  1037.                         ison= (*answer != '0');
  1038.                         }
  1039.                     }
  1040.                 aview = new DCheckBox( anAsker->fKind, super, NULL);
  1041.                 aview->SetStatus( ison);
  1042.                 }
  1043.                 break;
  1044.                             
  1045.             
  1046.             case kGopherAskChoose:    
  1047.                 {
  1048.                 char *cp, *ep;
  1049.                 Boolean done;
  1050.                 DPopupList* aPopup = new DPopupList(anAsker->fKind, super, true);
  1051.                 
  1052.                 char *words= StrDup( anAsker->fAnswer);
  1053.                 for (cp= words, done=false; !done && *cp!=0; ) {
  1054.                     ep= strchr( cp, '\t');
  1055.                     if (!ep) {
  1056.                         ep=strchr( cp, '\0');
  1057.                         done= true;
  1058.                         }
  1059.                   if (ep) {
  1060.                         *ep= 0;
  1061.                         aPopup->AddItem( cp);
  1062.                         if (!done) cp= ep+1;
  1063.                         }
  1064.                     else
  1065.                         done= true;
  1066.                     }
  1067.                 MemFree( words);
  1068.                 aPopup->SetValue(1);
  1069.                 aview= aPopup;
  1070.                 }
  1071.                 break;
  1072.                 
  1073.             case kGopherAskNote: 
  1074.             default : 
  1075.                 aview = new DPrompt( anAsker->fKind, super, anAsker->fAnswer, 0, 0, gTextFont);
  1076.                 aview->SetResize( DView::relsuper, DView::fixed);
  1077.                 break;
  1078.  
  1079.             }
  1080.             
  1081.         if (aview) {
  1082.             if (cluster) fControls->InsertLast(cluster);
  1083.             else fControls->InsertLast(aview);
  1084.             //this->AddSubordinate( aview); //??? test utility of this
  1085.             }
  1086.         }
  1087.         
  1088.     //this->SetClusterPositions(); //??
  1089. #if 0        
  1090.     Nlm_RecT brect;
  1091.     this->GetPosition( brect);
  1092.     brect.bottom = Min( brect.bottom, aloc.bottom+2+Nlm_hScrollBarHeight);
  1093.     this->SetPosition( brect);
  1094. #endif
  1095. }
  1096.  
  1097. #endif  // OBSOLETE
  1098.  
  1099.  
  1100.